#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "symbol.h"
#include "array_signature.h"
#include "function_signature.h"
/*
struct symbol{
	enum type _type;
	char * _name;
	enum mode _mode;
	void * _infos;
};*/

struct symbol * symbol_create(){
	struct symbol * s = malloc(sizeof(*s));
	s->_name = NULL;
	s->_type = TYPE_VOID;
	s->_mode = MODE_VAR;
	s->_infos = NULL;
	return s;
}

void symbol_free(struct symbol * s){
	free(s->_name);
	if(s->_infos){
		switch(s->_mode){
			case MODE_ARRAY:
				array_free(s->_infos);
				break;
			case MODE_FUNCTION:
				function_free(s->_infos);
				break;
		}
	}
}

int symbol_set_type(struct symbol * s, enum type type){
	if(s != NULL){
		s->_type = type;
	}
	return -1;
}

enum type symbol_get_type(struct symbol *s){
	return s->_type;
}

int symbol_set_name(struct symbol * s, char * name){
	if(s != NULL){
		if(s->_name != NULL){
			free(s->_name);
		}
		s->_name = malloc((strlen(name)+1));
		strcpy(s->_name, name);
		return 0;
	}
	return -1;
}
char * symbol_get_name(struct symbol *s){
	return s->_name;
}

int symbol_set_mode(struct symbol * s, enum mode mode){
	if(s != NULL){
		if(mode == MODE_ARRAY && s->_type == TYPE_FLOAT){
			s->_mode = mode;
			return 0;
		}else if(mode == MODE_FUNCTION && s->_type != TYPE_FLOAT){
			s->_mode = mode;
			return 0;
		}
		return -2;
	}
	return -1;
}
enum mode symbol_get_mode(struct symbol * s){
	return s->_mode;
}

int symbol_set_infos(struct symbol * s, void * info){
	s->_infos = info;
	return 0;
}

struct array_signature * symbol_get_array(struct symbol * s){
	return (s->_infos == NULL || s->_mode != MODE_ARRAY) ? NULL : (struct array_signature *)s->_infos;
}

struct function_signature * symbol_get_function(struct symbol * s){
	return (s->_infos == NULL || s->_mode != MODE_FUNCTION) ? NULL : (struct function_signature *)s->_infos;
}

void symbol_print_type(struct symbol * s){
	switch(s->_type){
		case TYPE_VOID:
			printf("void");
			break;
		case TYPE_INT:
			printf("int");
			break;
		case TYPE_FLOAT:
			printf("float");
			break;
	}
}
void symbol_print_name(struct symbol * s){
	printf("%s", s->_name);
}
void symbol_print_def(struct symbol *s){
	symbol_print_type(s);
	printf(" ");
	symbol_print_name(s);
	switch(s->_mode){
		case MODE_ARRAY:
			printf(" ");
			struct array_signature * a = symbol_get_array(s);
			array_print(a);
			break;
		case MODE_FUNCTION:
			printf(" ");
			struct function_signature * f = symbol_get_function(s);
			function_print_signature(f);
			break;
		default:
			return;
	}
}

void symbol_print(struct symbol * s){
	symbol_print_def(s);
}